package com.karaku.karaku_collector.agora;

import android.os.Handler;
import android.os.Looper;
import android.view.SurfaceView;

import com.karaku.karaku_collector.App;
import com.karaku.karaku_collector.BuildConfig;
import com.karaku.karaku_collector.LocalSetting;
import com.karaku.karaku_collector.collector.renderer.CustomizedCameraRenderer;

import javax.microedition.khronos.egl.EGLContext;

import io.agora.rtc.Constants;
import io.agora.rtc.RtcEngine;
import io.agora.rtc.video.AgoraVideoFrame;

/**
 * Created by guoping on 2017/10/26.
 */

public class AgoraManager {

    public interface Listener {

        void onOpenCameraFailed();

        void onNewView(SurfaceView surfaceView);

        void onDeleteView(SurfaceView surfaceView);

        void onStartFailed();
    }

    private static AgoraManager instance;
    public static AgoraManager getInstance() {
        return instance;
    }

    public static AgoraManager start(final String channelKey, final String channelId, final int uid, final int videoProfile, final Listener listener) {
        int t = 0;
        if (instance != null) {
            instance.leaveChannel();
            t = 500;
        }

        instance = new AgoraManager(channelKey, channelId, uid, videoProfile, listener);
        instance.stopped = false;
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                if (instance.stopped) {
                    return;
                }
                instance.start();
            }
        }, t);
        return instance;
    }

    private Listener listener;
    private String channelKey;
    private String channelId;
    private int uid;
    private int videoProfile = Constants.VIDEO_PROFILE_480P;
    private boolean stopped = true;
    private float scale;

    private RtcEngine rtcEngine;
    private CustomizedCameraRenderer surfaceView;

    private AgoraManager(String channelKey, String channelId, int uid, int videoProfile, Listener listener) {
        this.channelKey = channelKey;
        this.channelId = channelId;
        this.uid = uid;
        this.videoProfile = videoProfile;
        this.listener = listener;
        setScale(LocalSetting.getInstance().getScale());
    }

    public void leaveChannel() {
        stopped = true;
        stopLocalVideo();
        new Handler(Looper.getMainLooper()).post(new Runnable() {
            @Override
            public void run() {
                listener.onDeleteView(surfaceView);
            }
        });
        if (rtcEngine != null) {
            rtcEngine.leaveChannel();
            rtcEngine = null;
            RtcEngine.destroy();
        }
    }

    public SurfaceView getSurfaceView() {
        return surfaceView;
    }

    public void setScale(float scale){
        this.scale = scale;
        if (surfaceView != null) {
            surfaceView.setScale(scale);
        }
    }

    public void setWhiteBalance(float[] whiteBalance) {
        if (surfaceView != null) {
            surfaceView.setWhiteBalance(whiteBalance);
        }
    }

    private void start() {
        try {
            if (BuildConfig.AGORA_USE_STATIC_KEY) {
                rtcEngine = RtcEngine.create(App.getInstance(), BuildConfig.AGORA_STATIC_KEY, CollectorRtcEventHandler.getGlobalHandler());
            } else {
                rtcEngine = RtcEngine.create(App.getInstance(), BuildConfig.AGORA_KEY, CollectorRtcEventHandler.getGlobalHandler());
            }
            rtcEngine.setChannelProfile(Constants.CHANNEL_PROFILE_LIVE_BROADCASTING);
            if (rtcEngine.isTextureEncodeSupported()) {
                rtcEngine.setExternalVideoSource(true, true, true);
            } else {
                throw new RuntimeException("Can not work on device do not supporting texture" + rtcEngine.isTextureEncodeSupported());
            }
            rtcEngine.setVideoProfile(videoProfile, true); //swapWidthAndHeight
            rtcEngine.setClientRole(Constants.CLIENT_ROLE_BROADCASTER, null);
            rtcEngine.setEnableSpeakerphone(false);
            rtcEngine.enableWebSdkInteroperability(true);
            rtcEngine.muteLocalAudioStream(true);
            rtcEngine.muteAllRemoteAudioStreams(true);
            rtcEngine.muteAllRemoteVideoStreams(true);

            rtcEngine.enableVideo();
            setupLocalVideo();

//            surfaceView = RtcEngine.CreateRendererView(App.getInstance());
//            rtcEngine.setupLocalVideo(new VideoCanvas(surfaceView, VideoCanvas.RENDER_MODE_HIDDEN, uid));
//            rtcEngine.switchCamera();
            if (BuildConfig.AGORA_USE_STATIC_KEY) {
                rtcEngine.joinChannel(null, channelId, null, uid);
            } else {
                rtcEngine.joinChannel(channelKey, channelId, null, uid);
            }
            new Handler(Looper.getMainLooper()).post(new Runnable() {
                @Override
                public void run() {
                    listener.onNewView(surfaceView);
                }
            });
        } catch (Exception ex) {
            ex.printStackTrace();
            listener.onStartFailed();
        }
    }

    private void stopLocalVideo() {
        if (surfaceView != null) {
            surfaceView.onDestroy();
        }
    }

    private void setupLocalVideo() {
        surfaceView = new CustomizedCameraRenderer(App.getInstance(), LocalSetting.getInstance().getPreviewSize());
        surfaceView.setListener(new CustomizedCameraRenderer.Listener() {
            @Override
            public void onOpenCameraFailed() {
                if (listener != null) {
                    listener.onOpenCameraFailed();
                }
            }
        });
        surfaceView .setOnFrameAvailableHandler(new CustomizedCameraRenderer.OnFrameAvailableListener() {
            @Override
            public void onFrameAvailable(int texture, EGLContext eglContext, int rotation, int width, int height) {
                AgoraVideoFrame vf = new AgoraVideoFrame();
                vf.format = AgoraVideoFrame.FORMAT_TEXTURE_2D;
                vf.timeStamp = System.currentTimeMillis();
                vf.stride = width;
                vf.height = height;
                vf.textureID = texture;
                vf.syncMode = true;
                vf.eglContext11 = eglContext;
                vf.transform = new float[] {
                        1.0f, 0.0f, 0.0f, 0.0f,
                        0.0f, 1.0f, 0.0f, 0.0f,
                        0.0f, 0.0f, 1.0f, 0.0f,
                        0.0f, 0.0f, 0.0f, 1.0f
                };

                boolean result = rtcEngine.pushExternalVideoFrame(vf);
            }
        });
        surfaceView.setScale(scale);

        surfaceView.setOnEGLContextHandler(new CustomizedCameraRenderer.OnEGLContextListener() {
            @Override
            public void onEGLContextReady(EGLContext eglContext) {
            }
        });

        surfaceView.setZOrderMediaOverlay(true);
    }
}

